﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.Windows.Forms;
using System.ComponentModel;
using VersionComparer.Base;

namespace VersionComparer.Configuration
{
    public class ConfigurationHelper
    {
        #region statics
        static bool created;
        /// <summary>
        /// Returns the configuration path given a type
        /// </summary>
        /// <param name="type">type</param>
        /// <returns>configuration file path for this type</returns>
        private static string PathFromName(Type type)
        {
            string path =  string.Format("{0}\\VersionComparer\\{2}.{1}.xml", System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), ConfigurationNameAttribute.GetTypeConfigurationName(type), Path.GetFileNameWithoutExtension(typeof(ConfigurationHelper).Assembly.Location));
            if (!created)
            {
                //this may not seem thread safe, but actually it is - the CreateDirectory is thread safe by itself. The if is just for performance reasons
                created = true;
                Directory.CreateDirectory(Path.GetDirectoryName (path));
            }
            return path;
        }
    
        /// <summary>
        /// Serializes an entity to file
        /// </summary>
        /// <typeparam name="T">type of entity</typeparam>
        /// <param name="entity">entity to serialize</param>
        /// <returns>true if successfully serialized</returns>
        public static bool Save<T>(T entity)
        {
            try
            {
                XmlSerializer serializer = new XmlSerializer(entity.GetType());
                string path = PathFromName(entity.GetType());
                if (File.Exists(path))
                    File.Delete(path);
                using (FileStream stream = new FileStream(path, FileMode.CreateNew))
                {
                    serializer.Serialize(stream, entity);
                }
                return true;
            }
            catch (Exception ex)
            {
                if (MessageBox.Show(ex.Message, "Error", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error) == DialogResult.Cancel)
                    return false;
                else
                    return Save( entity);
            }
        }

        /// <summary>
        /// Deserializes an entity of the given type
        /// </summary>
        /// <typeparam name="T">base type of entity</typeparam>
        /// <param name="type">type of entity</param>
        /// <param name="ignoreError">if true exceptions are ignored and default(T) is returned</param>
        /// <returns>previously serialized type</returns>
        public static T Load<T>(Type type , bool ignoreError = true)
        {
            try
            {
                XmlSerializer serializer = new XmlSerializer(type);
                if (File.Exists(PathFromName(type)))
                {
                    using (FileStream stream = new FileStream(PathFromName(type), FileMode.Open))
                    {
                        return (T)serializer.Deserialize(stream);
                    }
                }
                else
                    return (T)Activator.CreateInstance(type);
            }
            catch (Exception ex)
            {
                if (ignoreError)
                    return (T)Activator.CreateInstance(type);
                if (MessageBox.Show(ex.Message, "Error", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error) == DialogResult.Cancel)
                    return (T)Activator.CreateInstance(type);
                else
                    return Load<T>(ignoreError);
            }
        }
        /// <summary>
        /// Deserializes an entity of the given type
        /// </summary>
        /// <typeparam name="T">type of entity</typeparam>
        /// <param name="ignoreError">if true exceptions are ignored and default(T) is returned</param>
        /// <returns>previously serialized type</returns>
        public static T Load<T>(bool ignoreError = true)
        {
            return  Load<T>(typeof(T), ignoreError);
        }

       
        #endregion statics

    }
}
